(* en ASV
	module Env = Map.Make (String)
*)

type expr =
	| Int of int
	| Ope of (int->int->int)
			* expr * expr
	| Var of string
	| Let of string * expr * expr

let rec assoc x = function
	| [] 			-> failwith ""
	| (k,v)::_ when x = k 	-> v
	| _::t 			-> assoc x t

let rec eval env = function
	| Int i 
		-> i
	| Ope (o,e1,e2) 
		-> o (eval env e1) (eval env e2)
	| Var x 
		-> assoc x env
		(* en imperatif
			Hashtbl.find env x
		*)
		(* en ASV
			Env.find x env
		*)
	| Let (x,e1,e2)
		-> eval ((x,eval env e1)::env) e2
		(* en imperatif
			Hashtbl.add env x (eval env e1);
			let r = eval env e2 in
				Hashtbl.remove env x;
				r
                *)
                (* en ASV
                        eval ( Env.add x (eval env e1) env ) e2
                *)




let res = 
	Let("x", Int 1,Ope ((+),Let("x",Int 2,Ope(( * ), Var "x", Int 2)),
	Var "x"))
	
